package com.wmd.core.conf;

import com.alibaba.fastjson.JSON;
import com.wmd.core.annotation.NoneConvertResult;
import com.wmd.core.exceptions.GenericResponse;
import com.wmd.core.exceptions.MyException;
import com.wmd.core.exceptions.ValidationException;
import com.wmd.validation.LogInterfaceHistory.LogHistory;
import com.wmd.validation.aop.LogManage;
import com.wmd.validation.util.LogMessage;
//import org.apache.shiro.authz.AuthorizationException;
//import org.apache.shiro.authz.UnauthenticatedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;


/**
 * controller 增强器 原理是使用AOP对Controller控制器进行增强（前置增强、后置增强、环绕增强）
 * 启动应用后，被 @ExceptionHandler、@InitBinder、@ModelAttribute 注解的方法，都会作用在 被 @RequestMapping 注解的方法上。
 * @ModelAttribute：在Model上设置的值，对于所有被 @RequestMapping 注解的方法中，都可以通过 ModelMap获取，或者通过@ModelAttribute("author")也可以获取
 * @ExceptionHandler 拦截了异常，我们可以通过该注解实现自定义异常处理。其中，@ExceptionHandler 配置的 value 指定需要拦截的异常类型，下面拦截了 Exception.class 这种异常。
 * @author zhaojq
 * @since 2020/12/10
 */
//@ControllerAdvice(basePackages = "com.wmd.**.controller")
@ControllerAdvice(annotations = RestController.class)
public class MyControllerAdvice implements ResponseBodyAdvice<Object> {

    Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired(required = false)
    private LogHistory logHistory;
    /**
     * 应用到所有@RequestMapping注解方法，在其执行之前初始化数据绑定器
     * @param binder
     */
    @InitBinder
    public void initBinder(WebDataBinder binder) {}
//    @ResponseBody
//    @ExceptionHandler(AuthorizationException.class)
//    public GenericResponse handleAuthorizationException(AuthorizationException ex) {
//        //ex.getException().printStackTrace();
//        logger.error(ex.getMessage());
//        GenericResponse gr= new GenericResponse(401, ex.getMessage(), ex.getLocalizedMessage());
//        return gr;
//    }
//
//
//
//    @ResponseBody
//    @ExceptionHandler(UnauthenticatedException.class)
//    public GenericResponse handleUnauthenticatedException(UnauthenticatedException ex) {
//        //ex.getException().printStackTrace();
//        logger.error(ex.getMessage());
//        GenericResponse gr= new GenericResponse(401, "未登录", "");
//        return gr;
//    }
    /**
     * 全局异常捕捉处理
     * @param ex
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public GenericResponse errorHandler(Exception ex) {
        ex.printStackTrace();
        GenericResponse gr=  new GenericResponse(1000, ex.getMessage(), null);
//                ResponseFormat.retParam(1000,ex.getMessage());
        LogManage.printOptLog(gr.getCode(), this.logHistory);
        return gr;
    }



    /**
     * 拦截捕捉自定义异常 MyException.class
     * @param ex
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = MyException.class)
    public GenericResponse myErrorHandler(MyException ex) {
        //ex.getException().printStackTrace();
        logger.error(ex.getMessage());
        GenericResponse gr= new GenericResponse(ex.getCode(), ex.getMessage(), ex.getException());
        LogManage.printOptLog(gr.getCode(), this.logHistory);
        return gr;
    }
    @ResponseBody
    @ExceptionHandler(value = ValidationException.class)
    public GenericResponse myValidationErrorHandler(ValidationException ex) {
        //ex.getException().printStackTrace();
        logger.error(ex.getMessage());
        GenericResponse gr= new GenericResponse(ex.getCode(), ex.getMessage(), ex.getInfos());
        LogManage.printOptLog(gr.getCode(), this.logHistory);
        return gr;
    }


    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        NoneConvertResult ann=returnType.getMethodAnnotation(NoneConvertResult.class);
        if(ann!=null){
            return body;
        }
        NoneConvertResult classann=returnType.getDeclaringClass().getAnnotation(NoneConvertResult.class);
        if(classann!=null){
            return body;
        }
        GenericResponse gr;
        if(null == body) {
            if(returnType.getMethod().getReturnType().equals(void.class)){
                return body;
            }else {
                gr= new GenericResponse(200, "数据为空", null);
            }
        }else if(!(body instanceof GenericResponse)) {
           gr= new GenericResponse(200, "成功", body);
        }else{
            gr=(GenericResponse)body;
        }
        LogManage.printOptLog(gr.getCode(), this.logHistory);
        if(body instanceof String){
            return JSON.toJSONString(gr);
        }else{
            return gr;
        }

    }
}